package com.appkubes.fintech.admin.application.signature.wukong.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.appkubes.fintech.admin.application.bill.dao.RentBillHeaderDao;
import com.appkubes.fintech.admin.application.order.dao.RentOrderDao;
import com.appkubes.fintech.admin.application.signature.wukong.helper.constant.ConfigConstant;
import com.appkubes.fintech.admin.application.signature.wukong.helper.exception.DefineException;
import com.appkubes.fintech.admin.application.signature.wukong.helper.helper.*;
import com.appkubes.fintech.admin.application.signature.wukong.service.WukongSignService;
import com.appkubes.fintech.admin.application.user.dao.UserBaseInfoDao;
import com.appkubes.fintech.common.exption.BusinessException;
import com.appkubes.fintech.common.response.Response;
import com.appkubes.fintech.core.po.*;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Slf4j
public class WukongSignServiceImpl implements WukongSignService {

    @Resource
    private RentOrderDao rentOrderDao;

    @Resource
    private UserBaseInfoDao userBaseInfoDao;

    @Resource
    private RentBillHeaderDao rentBillHeaderDao;

    @Value("${wukong.data.apiUrl}")
    private String host;

    @Value("${wukong.data.projectId}")
    private String projectId;

    @Value("${wukong.data.projectSecret}")
    private String projectSecret;

    //这个模板id是先执行代码上传模板得到的uploadTemplate
    @Value("${wukong.data.templateId}")
    private String templateId;

    @Value("${wukong.data.templateIdZuNin}")
    private String templateIdZuNin;

    //机构id，我们机构只有一个，所以创建过一次之后，就可以吧换个orgid存起来长期用
    @Value("${wukong.data.orgId}")
    private String orgId;

    @Value("${wukong.data.company_name}")
    private String company_name;
    @Value("${wukong.data.company_id_number}")
    private String company_id_number;

    @Value("${wukong.data.company_phone}")
    private String company_phone;

    @Value("${wukong.data.company_address}")
    private String company_address;

    @Value("${wukong.data.company_email}")
    private String company_email;

    @Override
    public Response signAuto(String orderKey) {
        try {
            initSetting();
            //获取订单信息
            FintechRentOrder order = rentOrderDao.selectByPrimaryKey(orderKey);
            if (order == null) {
                return Response.fail("订单信息错误");
            }
            //判断是否签章
            if (order.getContractUrl()!=null && !order.getContractUrl().equals("")) {
                //"该订单已经签章过，无需重复签章"
                log.info("该订单已经签章过，无需重复签章");
                return Response.success(order.getContractUrl());
            }
            //获取用户信息
            String userKey = order.getUserKey();
            FintechUserBaseInfo baseInfo = userBaseInfoDao.selectByPrimaryKey(userKey);
            if (baseInfo == null) {
                return Response.fail("用户信息错误");
            }

            //签章开始-----------start--------------------

            Random random = new Random();
            String thirdPartyUserId = userKey+random.nextInt(10000);
            String fileUrl = this.extsignAuto(thirdPartyUserId,baseInfo,order);
             //签章结束-----------end----------------------
            return Response.success(fileUrl);
        } catch (DefineException e) {
            log.error("合同签署异常：" + e.getE().getMessage(),e);
            return Response.fail("合同签署异常");
        } catch (Exception e) {
            log.error("合同签署异常：" + e.getMessage(),e);
            return Response.fail("合同签署异常");
        }
    }

    private void initSetting() {
        ConfigConstant.host = host;
        ConfigConstant.PROJECT_ID = projectId;
        ConfigConstant.PROJECT_SECRET = projectSecret;
    }

    //上传合同模板
    private void uploadTemplate() {
        try {
            initSetting();
            TokenHelper.getTokenData();

            String filePath = "C:/Users/CPF/Desktop/contract.pdf";
            JSONObject uploadJson = FileTemplateHelper.createTemplateByUpload(filePath, "contract.pdf");
            String uploadUrl = uploadJson.getString("uploadUrl");
            String templateId = uploadJson.getString("templateId");
            FileTemplateHelper.streamUpload(filePath, uploadUrl);
            log.info("悟空模板上传模板id="+templateId);
        }
        catch (Exception e) {
            log.info("悟空模板上传模板出错，msg="+e.getMessage());
        }
    }

    private void createFileByUpload() {
        try {
            initSetting();
            TokenHelper.getTokenData();

            String filePath = "C:/Users/CPF/Desktop/contract.pdf";
            JSONObject uploadJson = FileTemplateHelper.createFileByUpload(filePath, "test.pdf");
            String uploadUrl = uploadJson.getString("uploadUrl");
            String templateId = uploadJson.getString("templateId");
            FileTemplateHelper.streamUpload(filePath, uploadUrl);
            log.info("悟空模板上传模板id="+templateId);
        }
        catch (Exception e) {
            log.info("悟空模板上传模板出错，msg="+e.getMessage());
        }
    }


    public String extsignAuto (String thirdPartyUserId, FintechUserBaseInfo baseInfo, FintechRentOrder order)throws Exception{
        // 获取token
        TokenHelper.getTokenData();

        //1 创建个人账号
        JSONObject personAcctJson = AccountHelper.createPersonAcct(thirdPartyUserId, baseInfo.getRealName(), null, baseInfo.getIdentityNum(), baseInfo.getPhone(), null);
        String acctId = personAcctJson.getString("accountId");
        // 创建个人模板印章，有需要再创建，正常用不到
        //JSONObject personSealJson = this.createPersonTemplateSeal(acctId, baseInfo.getRealName()+"个人印章", "RED", null, null, "BORDERLESS");;

        //2，创建机构账号（同一个机构创建过了不需要再次创建）
        if (orgId.equals("")) {
            thirdPartyUserId = thirdPartyUserId + "_org";
            JSONObject orgAcctJson = AccountHelper.createOrgAcct(thirdPartyUserId, acctId, company_name, null, company_id_number);//公司名,证件号
            orgId = orgAcctJson.getString("orgId");
            log.info("机构账号id="+orgId);
            // 创建机构印章  有需要再创建，正常用不到
            //JSONObject orgSealJson = SealHelper.createOrgTemplateSeal(orgId, baseInfo.getRealName()+"公司印章", "BLUE", null, null, null, null, "TEMPLATE_ROUND", "STAR");
            //String orgSealId = orgSealJson.getString("sealId");
        }

        //3，创建印章 （用默认的即可，无需再次创建）
        //4，上次签署文件 （已经在启动之前，执行过uploadTemplate获取的带templateFileId）
//        this.uploadTemplate();


        //模板填充
        JSONObject templateObject = this.createByTemplate(templateId,baseInfo,order); //数据填充
        templateId = templateObject.getString("fileId");
//        this.searchWordsPosition(templateId);//查坐标
        //5，创建签署流程
        JSONObject flowJson = SignHelper.createSignFlow();
        String flowId = flowJson.getString("flowId");

        //6, 流程文档添加 必做步骤
        SignHelper.addFlowDoc(flowId, templateId);

        //7, 增加流程签署附件 (选填，无需增加)

        //8， 增加签署区（包括平台，企业，用户）
        JSONObject jsonObject = SignHelper.addPlatformAutoSignArea(flowId, Lists.newArrayList(templateId), Lists.newArrayList("e6ecb2fd-e4ec-4c04-be97-85c3d46a960e"));

        JSONObject jsonObject2 = SealHelper.qryPersonSeal(acctId,1,10);
        JSONArray seals = jsonObject2.getJSONArray("seals");
        if (seals== null || seals.size()<=0)
            throw new BusinessException("获取不到个人印章");
        String personSealId = seals.getJSONObject(0).getString("sealId");
        String deadLine =  "2099-01-01 00:00:00";
        AccountHelper.setAutoSign(acctId,deadLine);//自动签署 需要先开通静默授权
        JSONObject jsonObject1 = SignHelper.addSignerAutoSignArea(flowId, Lists.newArrayList(templateId), Lists.newArrayList(acctId), Lists.newArrayList(personSealId));

        JSONObject jsonObject3 = SealHelper.qryOrgSeal(orgId,1,10);
        JSONArray orgSeals = jsonObject3.getJSONArray("seals");
        if (orgSeals== null || orgSeals.size()<=0)
            throw new BusinessException("获取不到机构印章");
        String orgSealId = orgSeals.getJSONObject(0).getString("sealId");
        AccountHelper.setAutoSign(orgId,deadLine);//自动签署 需要先开通静默授权
        JSONObject jsonObject4 = SignHelper.addOrganSignArea(flowId, Lists.newArrayList(templateId), Lists.newArrayList(orgId), Lists.newArrayList(orgSealId));

        //9,开启签署流程
        SignHelper.startSignFlow(flowId);

        //10 签署完成后，通知回调，平台方进行签署流程归档(已经设置成自动签署，无需要手动签署，但是由于第三方是异步的，所以需要查询签署状态)
        //SignHelper.archiveSignFlow(flowId);

        String fileUrl = "";
        //第三方是异步进行的，所以这里需要等待
        int retryCount = 0;
        while (true) {
            sleep(1000L);

            JSONObject queryJson = SignHelper.qrySignFlow(flowId);
            if (queryJson.getInteger("flowStatus")==1) {
                retryCount++;
                if (retryCount>10) {
                    log.error("悟空签章异常：签署状态获取失败");
                    //如果重试3次都没完成，则直接查询url存入数据库
                    JSONObject urlJson = SignHelper.qrySignUrl(flowId,acctId,"","0");
                    fileUrl = urlJson.getJSONObject("data").getString("shortUrl");
                    break;
                }
                else
                    continue;
            }
            else {
                break;
            }
        }

        if (fileUrl.equals("")) {
            //11 归档后，获取文件下载地址
            JSONObject docJsonObject = SignHelper.downloadFlowDoc(flowId);
            JSONArray docs = docJsonObject.getJSONArray("docs");
            if (docs == null || docs.size()==0) {
                throw new BusinessException("获取不到签章合同");
            }
            fileUrl = docs.getJSONObject(0).getString("fileUrl");
        }

        rentOrderDao.updateOrderContractUrl(fileUrl,order.getOrderKey());
        return fileUrl;
    }

    public static void sleep(Long millis) {
        try {
            Thread.sleep(millis); // 等待millis秒后继续
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }


    private void addComponents(String templateId,JSONArray structComponents) throws DefineException {
        log.error("添加项组件开始");
        FileTemplateHelper.addComponents(templateId,structComponents);
        log.error("添加项组件结束");
    }

    /***
     * 模板填充
     */
    public JSONObject createByTemplate(String templateId,FintechUserBaseInfo baseInfo,FintechRentOrder order) throws DefineException {

        Map<String, Object> paramter = new HashMap<>();

        //查询header
        FintechRentBillHeaderExample  example = new FintechRentBillHeaderExample();
        FintechRentBillHeaderExample.Criteria criteria = example.createCriteria();
        criteria.andOrderKeyEqualTo(order.getRentOrderKey());

        List<FintechRentBillHeader> headerList = rentBillHeaderDao.selectByExample(example);
        if(headerList.size()<0){
            log.error("查询header失败");
        }
        FintechRentBillHeader header = headerList.get(0);
        //查询租赁单详细

        SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        int curYear = calendar.get(Calendar.YEAR);
        int curMonth = calendar.get(Calendar.MONTH) +1;
        int curDay = calendar.get(Calendar.DATE);
        //合同头
        paramter.put("Text1", company_name);//甲方
        paramter.put("Text2", company_address);//甲方地址
        paramter.put("Text3", company_phone);//甲方联系方式
        paramter.put("Text4", company_email);//甲方邮箱
        paramter.put("Text5", baseInfo.getRealName());//乙方
        paramter.put("Text6", baseInfo.getIdentityNum() );//乙方身份证号码
        paramter.put("Text7", baseInfo.getPhone());//乙方联系方式
        paramter.put("Text8", baseInfo.getLivingProvince()+baseInfo.getLivingCity()+baseInfo.getLivingDistrict()+baseInfo.getLivingDetail());//乙方居住地址
        paramter.put("Text9", "");//乙方邮箱
        //合同头
//        //订单部分
        paramter.put("Text10", order.getRentOrderNo());//订单编号
        paramter.put("Text11", order.getGoodsTitle() );//设备型号
        paramter.put("Text12", order.getPeriodDays());//服务期限
        paramter.put("Text13",   order.getPeriods());//服务期数
        paramter.put("Text14",  (header.getBillAmount()+header.getBillInterest())/100/header.getPeriodsDays()  );//每天费用  （当期还款金额+利息）/100
//        Long peroidDays=DateUtil.between(header.getRentStartDate(),header.getRentEndDate(), DateUnit.DAY);
        paramter.put("Text15", "每"+this.getType(order.getPeriodType()));//还款日：
        paramter.put("Text16", "0");//意外保障费用
        paramter.put("Text17", "0");//押金总额
        paramter.put("Text18", "0");//免押金额
        paramter.put("Text19",order.getBuyOutAmount() );//到期买断价格
        paramter.put("Text20", ft.format(order.getRentStartDate()));//租赁起始日期
        paramter.put("Text21", ft.format(header.getRentEndDate()));//租赁结束日期
        paramter.put("Text22", ( (header.getUnpayAmount()!=null?header.getUnpayAmount():0) +(header.getUnpayInterestAmount()!=null?header.getUnpayInterestAmount():0))/100);//每期还款
        paramter.put("Text23", ( (header.getBillAmount()!=null?header.getBillAmount():0)+ (header.getBillInterest()!=null?header.getBillInterest():0))/100);//应还总租金
        //订单部分

        //配件信息部分
        //1件   默认手机
        paramter.put("Text24", "原装配件");//配件名称
        paramter.put("Text25", "1");//件数
        //2件
        paramter.put("Text26", "");//配件名称
        paramter.put("Text27", "");//件数
        paramter.put("Text28", "");//配件名称
        paramter.put("Text29", "");//件数
        paramter.put("Text30", "");//配件名称
        paramter.put("Text31", "");//件数
        paramter.put("Text32", "");//配件名称
        paramter.put("Text33", "");//件数
        paramter.put("Text34", "");//配件名称
        paramter.put("Text35", "");//件数
        paramter.put("Text36", "");//配件名称
        paramter.put("Text37", "");//件数
        paramter.put("Text38", "");//配件名称
        paramter.put("Text39", "");//件数
        //配件信息部分

        //权力及义务
        paramter.put("Text40",order.getGoodsTitle() );//甲方提供给乙方的设备_______商品
        paramter.put("Text41", "官方");//为______正品
        //权力及义务

        //落款区
        paramter.put("Text42",company_name );//甲方
        paramter.put("Text43", baseInfo.getRealName());//乙方
        paramter.put("Text44",curYear + "-" + curMonth + "-" + curDay );//日期
        //落款区
        String templateName = "租赁合同";
        return FileTemplateHelper.createFileByTemplate(templateId,templateName,paramter);
    }

    private String getType(Integer type){
        String periodType = "";
        switch(type){
            case 1 :
                periodType = "日";
                break;
            case 2 :
                periodType = "周";
                break;
            case 3 :
                periodType = "月";
                break;
            case 4 :
                periodType = "年";
                break;
            default :
        }
        return periodType;
    }

    //搜索关键字坐标
    private void searchWordsPosition(String fileId) throws DefineException {
        log.info("查坐标开始");
         SignHelper.searchWordsPosition(fileId,"法律后果");
        log.info("查坐标结束");
    }

}
